package com.github.eclipseace.mybatis.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;

import org.apache.ibatis.plugin.Plugin;

/**
 * @author eclipseAce
 */
public final class ReflectionUtils {
	private ReflectionUtils() {
	}

	public static Field getField(Class<?> type, String name) {
		for (Class<?> iType = type; iType != null; iType = iType.getSuperclass()) {
			try {
				Field field = iType.getDeclaredField(name);
				if (field != null) {
					return field;
				}
			} catch (NoSuchFieldException ignored) {
			}
		}
		return null;
	}

	public static Object readField(Object object, String name) {
		if (object != null) {
			Field field = getField(object.getClass(), name);
			if (field != null) {
				if (!Modifier.isPublic(field.getModifiers()) && !field.isAccessible()) {
					field.setAccessible(true);
				}
				try {
					return field.get(object);
				} catch (IllegalAccessException ignored) {
				}
			}
		}
		return null;
	}

	public static Object unwrapPlugin(Object plugin) throws IllegalAccessException {
		Object target = plugin;
		while (true) {
			try {
				InvocationHandler handler = Proxy.getInvocationHandler(target);
				if (handler instanceof Plugin) {
					target = readField(handler, "target");
				} else {
					break;
				}
			} catch (IllegalArgumentException e) {
				break;
			}
		}
		return target;
	}
}
